<template>
  <div class="role-list-container">
    <a-card :bordered="false" class="search-card">
      <a-form layout="inline" :model="searchForm">
        <a-form-item label="角色名称">
          <a-input v-model:value="searchForm.roleName" placeholder="请输入角色名称" />
        </a-form-item>
        <a-form-item label="角色标识">
          <a-input v-model:value="searchForm.roleKey" placeholder="请输入角色标识" />
        </a-form-item>
        <a-form-item label="状态">
          <a-select v-model:value="searchForm.status" placeholder="请选择状态" style="width: 120px">
            <a-select-option value="0">启用</a-select-option>
            <a-select-option value="1">禁用</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item>
          <a-button type="primary" @click="handleSearch">查询</a-button>
          <a-button style="margin-left: 8px" @click="resetSearch">重置</a-button>
          <a-button type="primary" style="margin-left: 8px" @click="showDrawer" v-if="hasPermission('system::role::save')">新增</a-button>
        </a-form-item>
      </a-form>
    </a-card>
    
    <div class="divider" style="background: #f5f5f5; height: 16px;"></div>
    
    <a-drawer
      title="新增角色"
      :width="720"
      :visible="drawerVisible"
      :body-style="{ paddingBottom: '80px' }"
      @close="handleDrawerClose"
    >
      <a-form :model="formState" layout="vertical">
        <a-form-item label="角色名称" name="name">
          <a-input v-model:value="formState.name" placeholder="请输入角色名称" />
        </a-form-item>
        <a-form-item label="角色标识" name="roleKey">
          <a-input v-model:value="formState.roleKey" placeholder="请输入角色标识" :disabled="formState.id" />
        </a-form-item>
        <a-form-item label="显示顺序" name="roleSort">
          <a-input-number v-model:value="formState.roleSort" :min="0" />
        </a-form-item>
        <a-form-item label="状态" name="roleStatus">
          <a-switch
            v-model:checked="formState.roleStatus"
            checked-children="启用"
            un-checked-children="禁用"
          />
        </a-form-item>
        <a-form-item label="角色菜单">
          <a-tree
            v-model:checkedKeys="formState.menuIds"
            checkable
            :tree-data="menuTreeData"
            :fieldNames="{children: 'children', title: 'title', key: 'id'}"
            :selectable="false"
            :show-line="true"
            style="width: 100%; max-height: 400px; overflow: auto"
          />
        </a-form-item>
      </a-form>
      <div
        :style="{
          position: 'absolute',
          right: 0,
          bottom: 0,
          width: '100%',
          borderTop: '1px solid #e9e9e9',
          padding: '10px 16px',
          background: '#fff',
          textAlign: 'right',
          zIndex: 1,
        }"
      >
        <a-button style="margin-right: 8px" @click="drawerVisible = false">
          取消
        </a-button>
        <a-button type="primary" @click="handleSubmit">
          提交
        </a-button>
      </div>
    </a-drawer>
    
    <a-card :bordered="false" class="table-card">
      <a-table
        :columns="columns"
        :data-source="dataSource"
        :loading="loading"
        :pagination="pagination"
        row-key="id"
        @change="handleTableChange"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'status'">
            <a-switch 
              :checked="record.status === '0'" 
              @change="(checked) => handleStatusChange(record.id, checked)"
              :loading="record.id === statusLoadingId"
              checked-children="启用" 
              un-checked-children="禁用"
            />
          </template>
          <template v-else-if="column.key === 'action'">
            <a-space>
              <a-tooltip title="编辑">
                <a-button type="link" size="small" @click="handleEdit(record)">
                  <edit-outlined />
                </a-button>
              </a-tooltip>
              <a-tooltip title="删除">
                <a-button type="link" size="small" danger @click="handleDelete(record)">
                  <delete-outlined />
                </a-button>
              </a-tooltip>
            </a-space>
          </template>
        </template>
      </a-table>
    </a-card>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted } from 'vue';
import { getRoleListByPage, updateRoleStatus, saveOrUpdateRole, searchRoleInfoById, deleteRoleInfo } from '@/api/system/role';
import { searchAllMenuNode } from '@/api/system/menu';
import dayjs from 'dayjs';
import { EditOutlined, DeleteOutlined } from '@ant-design/icons-vue';
import { Modal } from 'ant-design-vue';
import { hasPermission } from '@/utils/permission.js';

const columns = [
  {
    title: '角色ID',
    dataIndex: 'id',
    key: 'id',
  },
  {
    title: '角色名称',
    dataIndex: 'name',
    key: 'name',
  },
  {
    title: '角色权限标识',
    dataIndex: 'roleKey',
    key: 'roleKey',
  },
  {
    title: '角色显示顺序',
    dataIndex: 'roleSort',
    key: 'roleSort',
  },
  {
    title: '状态',
    key: 'status',
  },
  {
    title: '创建时间',
    dataIndex: 'createDate',
    key: 'createDate',
    customRender: ({ text }) => dayjs(text).format('YYYY-MM-DD HH:mm:ss')
  },
  {
    title: '操作',
    key: 'action',
  },
];

const dataSource = ref([]);
const loading = ref(false);
const statusLoadingId = ref(null);
const pagination = reactive({
  current: 1,
  pageSize: 10,
  total: 0,
});

const searchForm = reactive({
  roleName: null,
  roleKey: null,
  status: null,
});

const fetchData = async () => {
  try {
    loading.value = true;
    const params = {
      ...searchForm,
      pageNum: pagination.current,
      pageSize: pagination.pageSize,
    };
    const res = await getRoleListByPage(params);
    dataSource.value = res.entity;
    pagination.total = res.count;
  } catch (error) {
    console.error(error);
  } finally {
    loading.value = false;
  }
};

const handleSearch = () => {
  pagination.current = 1;
  fetchData();
};

const resetSearch = () => {
  Object.assign(searchForm, {
    roleName: null,
    roleKey: null,
    status: null
  });
  handleSearch();
};

const handleStatusChange = async (id, checked) => {
  try {
    statusLoadingId.value = id;
    await updateRoleStatus({
      ids: [id]
    });
    fetchData();
  } catch (error) {
    console.error(error);
  } finally {
    statusLoadingId.value = null;
  }
};

const handleTableChange = (pag) => {
  pagination.current = pag.current;
  pagination.pageSize = pag.pageSize;
  fetchData();
};

const handleEdit = async (record) => {
  try {
    const res = await searchRoleInfoById({ id: record.id });
    formState.id = record.id;
    formState.name = res.name;
    formState.roleKey = res.roleKey;
    formState.roleSort = res.roleSort;
    formState.roleStatus = res.status === '0';
    formState.menuIds = res.menuIds;
    
    drawerVisible.value = true;
    await fetchMenuTree();
  } catch (error) {
    console.error(error);
  }
};

const drawerVisible = ref(false);

const handleDrawerClose = () => {
  drawerVisible.value = false;
  Object.assign(formState, {
    id: null,
    name: null,
    roleKey: null,
    roleSort: 0,
    roleStatus: 0,
    menuIds: []
  });
};
const formState = reactive({
  id: null,
  name: null,
  roleKey: null,
  roleSort: 0,
  roleStatus: 1,
  menuIds: []
});

const menuTreeData = ref([]);

const fetchMenuTree = async () => {
  try {
    const res = await searchAllMenuNode({ id: -1 });
    const sortedTree = res.menuInfoTree.sort((a, b) => a.sort - b.sort);
    menuTreeData.value = sortedTree;
  } catch (error) {
    console.error(error);
  }
};

const showDrawer = () => {
  drawerVisible.value = true;
  fetchMenuTree();
};

const handleSubmit = async () => {
  try {
    await saveOrUpdateRole({
      id: formState.id,
      name: formState.name,
      roleKey: formState.roleKey,
      roleSort: formState.roleSort,
      roleStatus: formState.roleStatus,
      menuIds: formState.menuIds
    });
    handleDrawerClose();
    fetchData();
  } catch (error) {
    console.error(error);
  }
};

const handleDelete = async (record) => {
  Modal.confirm({
    title: '确认删除',
    content: `确定要删除角色"${record.name}"吗?`,
    okText: '确认',
    okType: 'danger',
    cancelText: '取消',
    async onOk() {
      try {
        await deleteRoleInfo({
          ids: [record.id]
        });
        fetchData();
      } catch (error) {
        console.error(error);
      }
    },
  });
};

onMounted(() => {
  fetchData();
});
</script>

<style scoped>
.role-list-container {
  padding: 0px;
}
.search-card {
  margin-bottom: 0px;
}
.table-card {
  margin-bottom: 0px;
}
</style>